package com.tkp.ExceptionHandler;

import com.alibaba.fastjson.JSONObject;
import com.tkp.entity.HttpException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: duk
 * @Date: 2021/11/9 20:32
 * @Description: 全局异常处理_对参数验证进行拦截处理
 */
@RestControllerAdvice
@Slf4j
public class BadRequestExceptionHandler {

    /**
     * 对方法参数校验异常处理方法(仅对于表单提交有效，对于以json格式提交将会失效)
     * 如果是表单类型的提交，则spring会采用表单数据的处理类进行处理（进行参数校验错误时会抛出BindException异常）
     * @param exception 异常数据
     * @return 状态码和异常信息
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<HttpException> handlerBindException(BindException exception) {
        return handlerValidException(exception);
    }

    /**
     * 对方法参数校验异常处理方法(前端提交的方式为json格式出现异常时会被该异常类处理)
     * json格式提交时，spring会采用json数据的数据转换器进行处理（进行参数校验时错误是抛出MethodArgumentNotValidException异常）
     * @param exception 异常数据
     * @return 状态码和异常信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<HttpException> handlerArgumentNotValidException(MethodArgumentNotValidException exception) {
        return handlerValidException(exception);
    }

    /**
     * 异常信息处理
     * @param e 异常信息
     * @return ResponseEntity信息
     */
    public ResponseEntity<HttpException> handlerValidException(Exception e) {
        HttpException httpException = new HttpException();
        log.debug("begin resolve argument exception");
        BindingResult result = null;
        if (e instanceof BindException) {
            BindException exception = (BindException) e;
            result = exception.getBindingResult();
        }
        Map<String, Object> maps;
        if (result != null && result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            maps = new HashMap<>(fieldErrors.size());
            fieldErrors.forEach(error -> {
                maps.put(error.getField(), error.getDefaultMessage());
            });
        } else {
            maps = Collections.EMPTY_MAP;
        }
        httpException.setMsg(HttpStatus.BAD_REQUEST.value(),maps);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(httpException);
    }
}
